home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- datetime.c
-
- This module converts RFC822 date/time lines into Mac-format date/time
- strings in local time.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
-
- #include "glob.h"
- #include "datetime.h"
- #include "strutil.h"
-
-
-
- /*----------------------------------------------------------------------------
- Skip
-
- Skip white space and comments.
-
- Entry: *str = string.
-
- Exit: *str = pointer to first character following skipped white space
- and comments.
- ----------------------------------------------------------------------------*/
-
- static void Skip (char **str)
- {
- char *s;
- short parenLevel;
-
- s = *str;
- while (true) {
- while (isLWSP(*s)) s++;
- if (*s == '(') {
- parenLevel = 1;
- s++;
- while (*s != 0 && parenLevel > 0) {
- if (*s == '(') {
- parenLevel++;
- } else if (*s == ')') {
- parenLevel--;
- }
- s++;
- }
- } else {
- break;
- }
- }
- *str = s;
- }
-
-
-
- /*----------------------------------------------------------------------------
- ParseNum
-
- Extract a long integer from a string.
-
- Entry: *str = string.
- min = minimum number of digits.
- max = maximum number of digits.
-
- Exit: function result = true if number parsed, false if syntax error.
- *num = the number
- *str = pointer to first character following parsed number.
- ----------------------------------------------------------------------------*/
-
- static Boolean ParseNum (char **str, short min, short max, short *num)
- {
- short n, numDigits;
- char *p;
-
- p = *str;
- if (!isdigit(*p)) return false;
- n = CrackNum(&p);
- numDigits = p - *str;
- if (numDigits < min || numDigits > max) return false;
- *str = p;
- *num = n;
- return true;
- }
-
-
-
- /*----------------------------------------------------------------------------
- FindDayOfWeek
-
- Given a string that might be a day of week abbreviation, return the number
- of the day of the week (starting with Monday = 1, ...).
-
- Entry: str = day of week string.
-
- Exit: function result = day of week ordinal, or 0 if can't parse.
- ----------------------------------------------------------------------------*/
-
- static short FindDayOfWeek (char *str)
- {
- static char *days[7] = {
- "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"
- };
- short i;
-
- for (i = 0; i < 7; i++) {
- if (MyStrNEqual(str, days[i], 3)) return i+1;
- }
- return 0;
- }
-
-
-
- /*----------------------------------------------------------------------------
- FindMonth
-
- Given a string that might be a month abbreviation, return the number
- of the month (starting with January = 1, ...).
-
- Entry: str = month string.
-
- Exit: function result = month ordinal, or 0 if can't parse.
- ----------------------------------------------------------------------------*/
-
- static short FindMonth (char *str)
- {
- static char *months[12] = {
- "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
- "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
- };
- short i;
-
- for (i = 0; i < 12; i++) {
- if (MyStrNEqual(str, months[i], 3)) return i+1;
- }
- return 0;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Parse822Date
-
- Parse a date/time that's in RFC822/1123 header format:
-
- Entry: date = RFC822/1123 date/time string.
-
- Exit: function result = number of seconds since January 1, 1904,
- the standard Mac date convention.
- function result = 0 if the date could not be parsed.
-
- date-time = [ day "," ] date time
-
- day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
-
- date = 1*2DIGIT month 2*4DIGIT
-
- month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
- "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
-
- time = hour zone
-
- hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
-
- zone = "UT" / "GMT" / "EST" / "EDT" / "CST" / "CDT" /
- "MST" / "MDT" / "PST" / "PDT" / ( ("+" / "-") 4DIGIT
- ----------------------------------------------------------------------------*/
-
- unsigned long Parse822Date (char *date)
- {
- DateTimeRec dt;
- unsigned long result;
- char *p;
- short sign = 1;
- short tzDelta = 0;
-
- memset(&dt, 0, sizeof(dt));
-
- p = date;
-
- /* Day of week and comma. */
-
- Skip(&p);
- if (isalpha(*p)) {
- if (FindDayOfWeek(p) == 0) return 0;
- p+= 3;
- Skip(&p);
- if (*p != ',') return 0;
- p++;
- }
-
- /* Date. */
-
- Skip(&p);
- if (!ParseNum(&p, 1, 2, &dt.day)) return 0;
-
- Skip(&p);
- dt.month = FindMonth(p);
- if (dt.month == 0) return 0;
- p += 3;
-
- Skip(&p);
- if (!ParseNum(&p, 2, 4, &dt.year)) return 0;
- if (dt.year < 21) {
- dt.year += 2000;
- } else if (dt.year < 100) {
- dt.year += 1900;
- }
-
- /* Time. */
-
- Skip(&p);
- if (!ParseNum(&p, 1, 2, &dt.hour)) return 0;
-
- Skip(&p);
- if (*p != ':') return 0;
- p++;
- Skip(&p);
- if (!ParseNum(&p, 2, 2, &dt.minute)) return 0;
-
- Skip(&p);
- if (*p == ':') {
- p++;
- Skip(&p);
- if (!ParseNum(&p, 2, 2, &dt.second)) return 0;
- }
-
- /* Zone. */
-
- Skip(&p);
- if (isalpha(*p)) {
- if (MyStrNEqual(p, "GMT", 3)) {
- tzDelta = 0;
- p += 3;
- } else if (MyStrNEqual(p, "UT", 2)) {
- tzDelta = 0;
- p += 2;
- } else if (MyStrNEqual(p, "EST", 3)) {
- sign = -1;
- tzDelta = 500;
- p += 3;
- } else if (MyStrNEqual(p, "EDT", 3)) {
- sign = -1;
- tzDelta = 400;
- p += 3;
- } else if (MyStrNEqual(p, "CST", 3)) {
- sign = -1;
- tzDelta = 600;
- p += 3;
- } else if (MyStrNEqual(p, "CDT", 3)) {
- sign = -1;
- tzDelta = 500;
- p += 3;
- } else if (MyStrNEqual(p, "MST", 3)) {
- sign = -1;
- tzDelta = 700;
- p += 3;
- } else if (MyStrNEqual(p, "MDT", 3)) {
- sign = -1;
- tzDelta = 600;
- p += 3;
- } else if (MyStrNEqual(p, "PST", 3)) {
- sign = -1;
- tzDelta = 800;
- p += 3;
- } else if (MyStrNEqual(p, "PDT", 3)) {
- sign = -1;
- tzDelta = 700;
- p += 3;
- } else {
- return 0;
- }
- } else if (*p == '+' || *p == '-') {
- sign = *p == '+' ? +1 : -1;
- p++;
- Skip(&p);
- if (!ParseNum(&p, 4, 4, &tzDelta)) return 0;
- } else {
- return 0;
- }
-
- Skip(&p);
- if (*p != 0) return 0;
-
- /* Convert to seconds since 1/1/1904 */
-
- DateToSeconds(&dt, &result);
- result -= sign * (3600*((long)tzDelta/100) + 60*((long)tzDelta%100));
- return result;
- }
-
-
- /*----------------------------------------------------------------------------
- Cleanup822Date
-
- Converts an RFC822 date/time string into a Mac-style date/time string
- in local time.
-
- Entry: date = RFC822 date/time string.
-
- Exit: date = Mac-style date/time string.
-
- If the string cannot be parsed or converted, or if the the use has
- not set the local time zone, the string is unchanged.
- ----------------------------------------------------------------------------*/
-
- void Cleanup822Date (char *date)
- {
- MachineLocation loc;
- long gmtOffset;
- unsigned long secs;
- Str255 time;
-
- /* Get our location. Return if Map control panel not installed. */
-
- ReadLocation(&loc);
- if (loc.latitude == 0 && loc.longitude == 0 && loc.u.gmtDelta == 0) return;
-
- /* Get our offset in seconds from GMT. */
-
- gmtOffset = loc.u.gmtDelta & 0x00FFFFFF;
- if ((gmtOffset & 0x00800000) != 0) gmtOffset |= 0xFF000000;
-
- /* Try to parse the date we were passed. */
-
- secs = Parse822Date(date);
- if (secs == 0) return;
-
- /* Correct for our timezone. */
-
- secs += gmtOffset;
-
- /* Convert it back into a Mac-style date/time string. */
-
- IUDateString(secs, abbrevDate, (StringPtr)date);
- p2cstr((StringPtr)date);
- strcat(date, " ");
- IUTimeString(secs, true, time);
- strcat(date, p2cstr(time));
- }
-